{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "b2bd82d7",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Python 3.9.7\r\n"
     ]
    }
   ],
   "source": [
    "!python -V"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "41062d8a",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "c984c564",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pickle"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "4add538c",
   "metadata": {},
   "outputs": [],
   "source": [
    "import seaborn as sns\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "8b135c2b",
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.feature_extraction import DictVectorizer\n",
    "from sklearn.linear_model import LinearRegression\n",
    "from sklearn.linear_model import Lasso\n",
    "from sklearn.linear_model import Ridge\n",
    "\n",
    "from sklearn.metrics import root_mean_squared_error"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "8e013caf",
   "metadata": {},
   "outputs": [],
   "source": [
    "df = pd.read_parquet('./data/green_tripdata_2021-01.parquet')\n",
    "\n",
    "df['duration'] = df.lpep_dropoff_datetime - df.lpep_pickup_datetime\n",
    "df.duration = df.duration.apply(lambda td: td.total_seconds() / 60)\n",
    "\n",
    "df = df[(df.duration >= 1) & (df.duration <= 60)]\n",
    "\n",
    "categorical = ['PULocationID', 'DOLocationID']\n",
    "numerical = ['trip_distance']\n",
    "\n",
    "df[categorical] = df[categorical].astype(str)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "116ff0cc",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "9.775464208836793"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "train_dicts = df[categorical + numerical].to_dict(orient='records')\n",
    "\n",
    "dv = DictVectorizer()\n",
    "X_train = dv.fit_transform(train_dicts)\n",
    "\n",
    "target = 'duration'\n",
    "y_train = df[target].values\n",
    "\n",
    "lr = LinearRegression()\n",
    "lr.fit(X_train, y_train)\n",
    "\n",
    "y_pred = lr.predict(X_train)\n",
    "\n",
    "root_mean_squared_error(y_train, y_pred)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "b134c97b",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/ubuntu/anaconda3/lib/python3.9/site-packages/seaborn/distributions.py:2619: FutureWarning: `distplot` is a deprecated function and will be removed in a future version. Please adapt your code to use either `displot` (a figure-level function with similar flexibility) or `histplot` (an axes-level function for histograms).\n",
      "  warnings.warn(msg, FutureWarning)\n",
      "/home/ubuntu/anaconda3/lib/python3.9/site-packages/seaborn/distributions.py:2619: FutureWarning: `distplot` is a deprecated function and will be removed in a future version. Please adapt your code to use either `displot` (a figure-level function with similar flexibility) or `histplot` (an axes-level function for histograms).\n",
      "  warnings.warn(msg, FutureWarning)\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<matplotlib.legend.Legend at 0x7fb6397fad60>"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "sns.distplot(y_pred, label='prediction')\n",
    "sns.distplot(y_train, label='actual')\n",
    "\n",
    "plt.legend()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "f9e6479e",
   "metadata": {},
   "outputs": [],
   "source": [
    "def read_dataframe(filename):\n",
    "    if filename.endswith('.csv'):\n",
    "        df = pd.read_csv(filename)\n",
    "\n",
    "        df.lpep_dropoff_datetime = pd.to_datetime(df.lpep_dropoff_datetime)\n",
    "        df.lpep_pickup_datetime = pd.to_datetime(df.lpep_pickup_datetime)\n",
    "    elif filename.endswith('.parquet'):\n",
    "        df = pd.read_parquet(filename)\n",
    "\n",
    "    df['duration'] = df.lpep_dropoff_datetime - df.lpep_pickup_datetime\n",
    "    df.duration = df.duration.apply(lambda td: td.total_seconds() / 60)\n",
    "\n",
    "    df = df[(df.duration >= 1) & (df.duration <= 60)]\n",
    "\n",
    "    categorical = ['PULocationID', 'DOLocationID']\n",
    "    df[categorical] = df[categorical].astype(str)\n",
    "    \n",
    "    return df"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "8029eba0",
   "metadata": {},
   "outputs": [],
   "source": [
    "df_train = read_dataframe('./data/green_tripdata_2021-01.parquet')\n",
    "df_val = read_dataframe('./data/green_tripdata_2021-02.parquet')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "f6f2f0eb",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(73908, 61921)"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(df_train), len(df_val)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "951d51ef",
   "metadata": {},
   "outputs": [],
   "source": [
    "df_train['PU_DO'] = df_train['PULocationID'] + '_' + df_train['DOLocationID']\n",
    "df_val['PU_DO'] = df_val['PULocationID'] + '_' + df_val['DOLocationID']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "c5cbfc25",
   "metadata": {},
   "outputs": [],
   "source": [
    "categorical = ['PU_DO'] #'PULocationID', 'DOLocationID']\n",
    "numerical = ['trip_distance']\n",
    "\n",
    "dv = DictVectorizer()\n",
    "\n",
    "train_dicts = df_train[categorical + numerical].to_dict(orient='records')\n",
    "X_train = dv.fit_transform(train_dicts)\n",
    "\n",
    "val_dicts = df_val[categorical + numerical].to_dict(orient='records')\n",
    "X_val = dv.transform(val_dicts)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "1e9fb68b",
   "metadata": {},
   "outputs": [],
   "source": [
    "target = 'duration'\n",
    "y_train = df_train[target].values\n",
    "y_val = df_val[target].values"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "429e2394",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "7.479513631630414"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "lr = LinearRegression()\n",
    "lr.fit(X_train, y_train)\n",
    "\n",
    "y_pred = lr.predict(X_val)\n",
    "\n",
    "root_mean_squared_error(y_val, y_pred)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "22bf6f8b",
   "metadata": {},
   "outputs": [],
   "source": [
    "with open('models/lin_reg.bin', 'wb') as f_out:\n",
    "    pickle.dump((dv, lr), f_out)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "a4999b94",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "11.167275941179728"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "lr = Lasso(0.01)\n",
    "lr.fit(X_train, y_train)\n",
    "\n",
    "y_pred = lr.predict(X_val)\n",
    "\n",
    "root_mean_squared_error(y_val, y_pred)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "47b0eb9b",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
